﻿using System;
using System.Collections.Generic;
using System.Text;
using ExpressionUtil.Extension;

namespace ExpressionUtil.Parser
{
    /// <summary>
    /// 解析的过程参数
    /// </summary>
    internal class ParseContext
    {
        /// <summary>
        /// 运算符优先级集合
        /// </summary>
        private static Dictionary<string, int> operatorPriority;

        /// <summary>
        /// 节点创建程序集合
        /// </summary>
        private static Dictionary<string, CreateNodeHandler> createHandlerMap;

        /// <summary>
        /// 扩展函数集合
        /// </summary>
        private static Dictionary<string, ExtensionFunction> extFunctionMap;

        /// <summary>
        /// 表达式扫描器
        /// </summary>
        private ExpressionScanner scanner;

        /// <summary>
        /// 解析出的变量集合
        /// </summary>
        private Dictionary<string, Node.VariableNode> variables;

        /// <summary>
        /// 解析的语法树堆栈
        /// </summary>
        private Stack<Node.Common.Node> postfixStack;

        /// <summary>
        /// 运算符堆栈
        /// </summary>
        private Stack<string> operatorStack;

        /// <summary>
        /// 参数个数堆栈
        /// </summary>
        private Stack<int> functionParameterCount;

        /// <summary>
        /// 当前解析的扩展函数名称
        /// </summary>
        private string currentExtFunctionName;

        /// <summary>
        /// 静态构造函数
        /// </summary>
        static ParseContext()
        {
            createHandlerMap = new Dictionary<string, CreateNodeHandler>();
            createHandlerMap.Add(",", Node.CommaNode.CreateCommaNode);
            createHandlerMap.Add("+", Node.AddNode.CreateAddNode);
            createHandlerMap.Add("-", Node.SubtractNode.CreateSubtractNode);
            createHandlerMap.Add("*", Node.MultiplicationNode.CreateMultiplicationNode);
            createHandlerMap.Add("/", Node.DivisionNode.CreateDivisionNode);
            createHandlerMap.Add("<<", Node.LeftShiftNode.CreateLeftShiftNode);
            createHandlerMap.Add(">>", Node.RightShiftNode.CreateRightShiftNode);
            createHandlerMap.Add("Unitary-", Node.NegativeNode.CreateNegativeNode);
            createHandlerMap.Add("Unitary+", Node.PositiveNode.CreatePositiveNode);
            createHandlerMap.Add(">", Node.GreaterThanNode.CreateGreaterThanNode);
            createHandlerMap.Add(">=", Node.GreaterOrEqualNode.CreateGreaterOrEqualNode);
            createHandlerMap.Add("<", Node.LessThenNode.CreateLessThanNode);
            createHandlerMap.Add("<=", Node.LessOrEqualNode.CreateLessOrEqualNode);
            createHandlerMap.Add("==", Node.EqualNode.CreateLogicEqualNode);
            createHandlerMap.Add("&&", Node.AndNode.CreateAndNode);
            createHandlerMap.Add("||", Node.OrNode.CreateOrNode);
            createHandlerMap.Add("!", Node.NotNode.CreateNotNode);
            createHandlerMap.Add("&", Node.LogicAndNode.CreateLogicAndNode);
            createHandlerMap.Add("|", Node.LogicOrNode.CreateLogicOrNode);
            createHandlerMap.Add("~", Node.LogicNotNode.CreateLogicNotNode);
            createHandlerMap.Add("Function_abs(", Node.AbsFunctionNode.CreateAbsFunctionNode);
            createHandlerMap.Add("Function_round(", Node.RoundFunctionNode.CreateRoundFunctionNode);
            createHandlerMap.Add("Function_trunc(", Node.TruncFunctionNode.CreateTruncFunctionNode);
            createHandlerMap.Add("Function_exp(", Node.ExpFunctionNode.CreateExpFunctionNode);
            createHandlerMap.Add("Function_sum(", Node.SumFunctionNode.CreateSumFunctionNode);
            createHandlerMap.Add("Function_avg(", Node.AvgFunctionNode.CreateAvgFunctionNode);
            createHandlerMap.Add("Function_ifelseif(", Node.IfElseIfFunctionNode.CreateIfElseIfFunctionNode);

            operatorPriority = new Dictionary<string, int>();
            operatorPriority.Add(",", 0);
            operatorPriority.Add("||", 6);
            operatorPriority.Add("&&", 6);
            operatorPriority.Add("&", 7);
            operatorPriority.Add("|", 7);
            operatorPriority.Add("~", 7);
            operatorPriority.Add(">", 8);
            operatorPriority.Add(">=", 8);
            operatorPriority.Add("<", 8);
            operatorPriority.Add("<=", 8);
            operatorPriority.Add("==", 8);
            operatorPriority.Add("<<", 9);
            operatorPriority.Add(">>", 9);
            operatorPriority.Add("+", 10);
            operatorPriority.Add("-", 10);
            operatorPriority.Add("*", 20);
            operatorPriority.Add("/", 20);
            operatorPriority.Add("Unitary-", 30);
            operatorPriority.Add("Unitary+", 30);
            operatorPriority.Add("!", 30);

            extFunctionMap = new Dictionary<string, ExtensionFunction>();
        }

        /// <summary>
        /// 获取或设置节点创建程序集合
        /// </summary>
        public static Dictionary<string, CreateNodeHandler> CreateHandlerMap
        {
            get
            {
                return createHandlerMap;
            }
            set
            {
                createHandlerMap = value;
            }
        }

        /// <summary>
        /// 获取或设置运算符优先级集合
        /// </summary>
        public static Dictionary<string, int> OperatorPriority
        {
            get
            {
                return operatorPriority;
            }
            set
            {
                operatorPriority = value;
            }
        }

        /// <summary>
        /// 获取或设置扩展函数集合
        /// </summary>
        public static Dictionary<string, ExtensionFunction> ExtFunctionMap
        {
            get
            {
                return extFunctionMap;
            }
            set
            {
                extFunctionMap = value;
            }
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="exp">需要解析的字符串</param>
        public ParseContext(string exp)
        {
            this.scanner = new ExpressionScanner(exp);
            this.operatorStack = new Stack<string>();
            this.postfixStack = new Stack<Node.Common.Node>();
            this.variables = new Dictionary<string, Node.VariableNode>();
            this.functionParameterCount = new Stack<int>();
            this.currentExtFunctionName = string.Empty;
        }

        /// <summary>
        /// 获取或设置表达式扫描器
        /// </summary>
        public ExpressionScanner Scanner
        {
            get
            {
                return this.scanner;
            }
            set
            {
                this.scanner = value;
            }
        }

        /// <summary>
        /// 获取或设置运算符堆栈
        /// </summary>
        public Stack<string> OperatorStack
        {
            get
            {
                return this.operatorStack;
            }
            set
            {
                this.operatorStack = value;
            }
        }

        /// <summary>
        /// 获取或设置解析的语法树堆栈
        /// </summary>
        public Stack<Node.Common.Node> PostfixStack
        {
            get
            {
                return this.postfixStack;
            }
            set
            {
                this.postfixStack = value;
            }
        }

        /// <summary>
        /// 获取或设置解析出的变量集合
        /// </summary>
        public Dictionary<string, Node.VariableNode> Variables
        {
            get
            {
                return this.variables;
            }
            set
            {
                this.variables = value;
            }
        }

        /// <summary>
        /// 获取或设置参数个数堆栈
        /// </summary>
        public Stack<int> FunctionParameterCount
        {
            get
            {
                return this.functionParameterCount;
            }
            set
            {
                this.functionParameterCount = value;
            }
        }

        /// <summary>
        /// 获取或设置当前解析的扩展函数名称
        /// </summary>
        public string CurrentExtFunctionName
        {
            get
            {
                return this.currentExtFunctionName;
            }
            set
            {
                this.currentExtFunctionName = value;
            }
        }

        /// <summary>
        /// 增加函数个数堆栈中栈顶元素数值
        /// </summary>
        public void IncreaseFunctionParameterCount()
        {
            this.IncreaseFunctionParameterCount(1);
        }

        /// <summary>
        /// 增加函数个数堆栈中栈顶元素数值
        /// </summary>
        /// <param name="count">指定增加的个数</param>
        public void IncreaseFunctionParameterCount(int count)
        {
            if (this.functionParameterCount.Count > 0)
            {
                int topCount = this.functionParameterCount.Pop();
                topCount += count;
                this.functionParameterCount.Push(topCount);
            }
        }
    }
}
